package com.dynamo.transport.network.practise.channel.socket.nio;

import com.dynamo.transport.network.practise.channel.Channel;
import com.dynamo.transport.network.practise.channel.ChannelFuture;
import org.apache.commons.collections.CollectionUtils;

import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * @author duanyimiao
 * @create 2018-12-17 11:48 AM
 * @description
 **/
public class NioBoss extends AbstractNioSelector implements Boss {

    @Override
    public Runnable createTask(Channel channel, ChannelFuture future) {
        return new RegisterTask(channel, future);
    }

    @Override
    public void process(Set<SelectionKey> keys) {
        if (CollectionUtils.isEmpty(keys)) {
            return;
        }
        for (Iterator<SelectionKey> it = keys.iterator(); it.hasNext(); ) {
            try {
                SelectionKey key = it.next();
                //有新的客户端连接
                NioServerSocketChannel serverChannel = (NioServerSocketChannel) key.attachment();
                //while (true) { //TODO how to break loop
                final SocketChannel socketChannel = serverChannel.channel.accept();
                //channel设置为非阻塞后，才能被selector进行监听
                //TODO 如何所有线程公用同一个ChannelPipeline，是否有安全问题
                socketChannel.configureBlocking(false);
                ((NioWorker)serverChannel.workerPool.nextWorker()).register(new NioAcceptSocketChannel(serverChannel.getPipeline(),socketChannel),null);
                System.out.println("NioBoss Receive Remote Channel ="+socketChannel);

                //   }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    private class RegisterTask implements Runnable {

        private Channel channel;
        private ChannelFuture future;

        RegisterTask(Channel channel, ChannelFuture future) {
            this.channel = channel;
            this.future = future;
        }

        @Override
        public void run() {
            try {
                //注册监听客户端连接事件
                ((NioServerSocketChannel) channel).channel.register(selector, SelectionKey.OP_ACCEPT, channel);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

}
